import numpy as np
from matplotlib import pyplot as plt
from numpy import interp
from sklearn.metrics import precision_recall_curve, average_precision_score, roc_curve
from log import log
from config import Config


class Plot:
    def __init__(self):
        pass

    def micro_PR(self, y_test, y_score):
        # 对每一个类别计算性能指标
        precisions = []
        recalls = []
        for i in range(Config.NUM_CLASSES):
            precision, recall, _ = precision_recall_curve(y_test[:, i], y_score[:, i])
            precisions.append(precision)
            recalls.append(recall)
        # .ravel()  将一个矩阵进行平展操作
        precision, recall, _ = precision_recall_curve(y_test.ravel(), y_score.ravel())
        precisions.append(precision)
        recalls.append(recall)
        all_precision = np.unique(np.concatenate([precisions[i] for i in range(Config.NUM_CLASSES)]))
        mean_recall = np.zeros_like(all_precision)
        for i in range(Config.NUM_CLASSES):
            mean_recall += interp(all_precision, precisions[i], recalls[i])
        mean_recall /= Config.NUM_CLASSES
        precision, recall = all_precision,mean_recall
        precisions.append(precision)
        recalls.append(recall)
        return precisions, recalls

    def micro_ROC(self, y_test, y_score):
        # 对每一个类别计算性能指标
        fprs = []
        tprs = []
        for i in range(Config.NUM_CLASSES):
            fpr, tpr, _ = roc_curve(y_test[:, i], y_score[:, i])
            fprs.append(fpr)
            tprs.append(tpr)
        fpr, tpr, _ = roc_curve(y_test.ravel(), y_score.ravel())
        # fpr, tpr, _ = roc_curve(val_targ.ravel(), val_predict.ravel())
        fprs.append(fpr)
        tprs.append(tpr)

        all_fpr = np.unique(np.concatenate([fprs[i] for i in range(Config.NUM_CLASSES)]))
        mean_tpr = np.zeros_like(all_fpr)
        for i in range(Config.NUM_CLASSES):
            mean_tpr += interp(all_fpr, fprs[i],tprs[i])
        mean_tpr /= Config.NUM_CLASSES

        fprs.append(all_fpr)
        tprs.append(mean_tpr)
        return fprs,tprs
    def plot_pr(self, y_test, y_score, labels: list[str], filename: str = None):
        plt.figure("P-R曲线")

        precision, recall= self.micro_PR(y_test, y_score)
        for i in range(len(precision)):
            label =  labels[i]
            plt.plot(recall[i], precision[i], lw=2, label=label)
        plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')

        plt.xlabel("Recall")
        plt.ylabel("Precision")
        plt.grid()
        plt.plot([0, 1.05], [0, 1.05], color="navy", ls="--")
        plt.legend(fontsize=8)
        plt.xlim(0, 1.05)
        plt.ylim(0, 1.05)
        # plt.title("PR曲线")
        if filename is not None:
            plt.savefig(filename)
        plt.show()

    def plot_acc(self, history, filename: str = None):
        print("history.history", history.history)
        plt.plot(history.history['accuracy'], label='accuracy')
        plt.plot(history.history['val_accuracy'], label='val_accuracy')
        plt.xlabel('Epoch')
        plt.ylabel('Accuracy')
        ylim = min([min(history.history['accuracy']), min(history.history['val_accuracy'])])
        log.info(str(ylim))
        ylim = int(ylim * 10) / 10
        log.info(str(ylim))
        plt.ylim([ylim, 1])
        plt.yticks()
        plt.legend(loc='lower right')
        if filename is not None:
            plt.savefig(filename)
        plt.show()

    def plot_ROC(self, y_test, y_score, labels: list[str], filename: str = None):
        plt.figure("ROC曲线")
        fprs, tprs = self.micro_ROC(y_test, y_score)
        for i in range(len(fprs)):
            plt.plot(fprs[i], tprs[i], label=labels[i])
        plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
        plt.xlim([0.0, 1.0])
        plt.ylim([0.0, 1.05])
        plt.xlabel('False Positive Rate')
        plt.ylabel('True Positive Rate')
        # plt.title('Receiver operating characteristic')
        plt.legend(loc="lower right")
        if filename is not None:
            plt.savefig(filename)
        plt.show()

